using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using SerialisationProject;

namespace Community.SharePoint.Tools.SPLookupLinker
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        Dictionary<string, SPList> listCollection;
        Dictionary<string, SPField> fieldCollection;
        Dictionary<string, SPField> lookupListFieldCollection;

        private void button1_Click(object sender, EventArgs e)
        {
            string url = textBoxSPWebUrl.Text;
            PopulateListCombos(url);
        }

        private void PopulateListCombos(string url)
        {
            if (url.Length > 0)
            {
                try
                {
                    listCollection = new Dictionary<string, SPList>();
                    comboBoxList.Items.Clear();
                    comboBoxLookupList.Items.Clear();

                    comboBoxField.Items.Clear();
                    comboBoxLookupField.Items.Clear();

                    comboBoxList.Items.Add("Select a list...");
                    comboBoxLookupList.Items.Add("Select a list...");

                    listCollection = SPOperations.GetLists(url);
                    foreach (string item in listCollection.Keys)
                    {
                        comboBoxList.Items.Add(item);
                        comboBoxLookupList.Items.Add(item);
                    }
                    comboBoxList.SelectedIndex = 0;
                    comboBoxLookupList.SelectedIndex = 0;
                }
                catch (Exception ex)
                {
                    ShowError(ex);
                }
            }
            else
            {
                ShowError("Please enter a URL");
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            PopulateFieldCombos();
        }

        private void buttonSchema_Click(Object sender, EventArgs e)
        {
            GetLookupFieldSchema();
            this.tabControl1.SelectTab(2);
            this.tabPage3.Select();
        }

        private void buttonLink2_Click(Object sender, EventArgs e)
        {
            RecreateLookupField();
        }

        private void PopulateFieldCombos()
        {
            string url = textBoxSPWebUrl.Text;

            if (comboBoxList.SelectedIndex > 0)
            {
                //Populate List Fields
                fieldCollection = new Dictionary<string, SPField>();

                string selectedItem = comboBoxList.Items[comboBoxList.SelectedIndex].ToString();
                if (selectedItem.Length > 0)
                {
                    SPList list = listCollection[selectedItem];
                    fieldCollection = SPOperations.GetFields(list);

                    comboBoxField.Items.Clear();
                    comboBoxField.Items.Add("Select a field...");

                    foreach (string item in fieldCollection.Keys)
                    {
                        comboBoxField.Items.Add(item);
                    }
                    comboBoxField.SelectedIndex = 0;
                }
            }

            if (comboBoxLookupList.SelectedIndex > 0)
            {
                //Populate List Fields
                lookupListFieldCollection = new Dictionary<string, SPField>();

                string selectedItem = comboBoxLookupList.Items[comboBoxLookupList.SelectedIndex].ToString();
                if (selectedItem.Length > 0)
                {
                    SPList lookupList = listCollection[selectedItem];
                    lookupListFieldCollection = SPOperations.GetFields(lookupList);
                    
                    comboBoxLookupField.Items.Clear();
                    comboBoxLookupField.Items.Add("Select a field...");

                    foreach (string lookupItem in lookupListFieldCollection.Keys)
                    {
                        comboBoxLookupField.Items.Add(lookupItem);
                    }
                    comboBoxLookupField.SelectedIndex = 0;
                }
            }
        }

        private void ShowError(Exception ex)
        {
            MessageBox.Show(ex.ToString(), "Error has occurred");
        }

        private void ShowError(string msg, Exception ex)
        {
            MessageBox.Show(string.Format("{0}\nDetails: {1}", msg, ex.ToString()), "Error has occurred");
        }

        private void ShowError(string msg)
        {
            MessageBox.Show(msg, "Error has occurred");
        }

        private void RecreateLookupField()
        {
            bool results = false;
            if (comboBoxField.SelectedIndex > 0 && comboBoxLookupField.SelectedIndex > 0)
            {
                if (MessageBox.Show("IMPORTANT: Ensure fields are lookups. Are you sure you want to continue?", "WARNING", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    try
                    {
                        SPList list = listCollection[comboBoxList.Items[comboBoxList.SelectedIndex].ToString()];
                        SPField field = fieldCollection[comboBoxField.Items[comboBoxField.SelectedIndex].ToString()];

                        SPList lookupList = listCollection[comboBoxLookupList.Items[comboBoxLookupList.SelectedIndex].ToString()];
                        SPField lookupListField = lookupListFieldCollection[comboBoxLookupField.Items[comboBoxLookupField.SelectedIndex].ToString()];


                        results = SPOperations.RecreateLookupField(list, field, lookupList, lookupListField);

                        if (results)
                        {
                            MessageBox.Show("Operation success.");
                        }
                        else
                        {
                            MessageBox.Show("Operation failed.");
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowError(ex);
                    }
                }
            }
            else
            {
                ShowError("Ensure both field comboboxes have been selected before continuing.");
            }
        }

        /// <summary>
        /// Get the lookup field schema
        /// </summary>
        private void GetLookupFieldSchema()
        {
            string results = string.Empty;
            if (comboBoxField.SelectedIndex > 0 && comboBoxLookupField.SelectedIndex > 0)
            {
                try
                {
                    SPList list = listCollection[comboBoxList.Items[comboBoxList.SelectedIndex].ToString()];
                    SPField field = fieldCollection[comboBoxField.Items[comboBoxField.SelectedIndex].ToString()];


                    results = SPOperations.GetFieldSchema(list, field);

                    textBoxList.Text = list.Title;
                    textBoxField.Text = field.Title;
                    textBoxSchema.Text = results;                    
                }
                catch (Exception ex)
                {
                    ShowError(ex);
                }
            }
        }

        private void buttonRunBatch_Click(object sender, EventArgs e)
        {
            ProcessBatch();
        }

        private void buttonLoad_Click(object sender, EventArgs e)
        {
            Batch batch = new Batch();
            string xmlPath = this.textBoxXmlPath.Text;
            int errors = 0;
            int operations = 0;

            if (xmlPath.Length > 0)
            {
                if (System.IO.File.Exists(xmlPath))
                {
                    string xml = FileHelper.Read(xmlPath);
                    batch = Batch.Deserialize(xml) as Batch;
                    this.progressBar1.Value = 0;
                    this.progressBar1.Minimum = 0;
                    this.progressBar1.Maximum = batch.Tasks.Count;

                    this.treeView1.Nodes.Clear();
                    TreeNode root = this.treeView1.Nodes.Add("File: " + textBoxXmlPath.Text);

                    foreach (Task t in batch.Tasks)
                    {
                        operations++;
                            
                        TreeNode child = root.Nodes.Add(string.Format("Task: {0}", operations.ToString()));
                        child.Nodes.Add(string.Format("SPWebUrl: '{0}'", t.SPWebUrl));
                        child.Nodes.Add(string.Format("ListName: '{0}'", t.ListName));
                        child.Nodes.Add(string.Format("FieldName: '{0}'", t.FieldName));
                        child.Nodes.Add(string.Format("LookupListName: '{0}'", t.LookupListName));
                        child.Nodes.Add(string.Format("LookupListFieldName: '{0}'", t.LookupListFieldName));

                        try
                        {
                            SPList list = SPOperations.GetList(t.SPWebUrl, t.ListName);
                            if (list == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or ListName.");
                            }
                            
                            SPField field = SPOperations.GetField(t.SPWebUrl, t.ListName, t.FieldName);
                            if (field == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or ListName or FieldName.");
                            }

                            SPList lookupList = SPOperations.GetList(t.SPWebUrl, t.LookupListName);
                            if (lookupList == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or LookupListName.");
                            }

                            SPField lookupListField = SPOperations.GetField(t.SPWebUrl, t.LookupListName, t.LookupListFieldName);
                            if (lookupListField == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or LookupListName or LookupListFieldName.");
                            }

                        }
                        catch (Exception ex)
                        {
                            errors++;
                            ShowError(string.Format("An error has occurred whilst processing Field ({0}) of List ({1}) at '{2}'.", t.FieldName, t.ListName, t.SPWebUrl), ex);
                        }
                        this.progressBar1.Value++;
                    }
                    if (errors > 0)
                    {
                        MessageBox.Show(string.Format("Operation completed, but with {0} error(s).", errors), "Operation Completed with errors");
                    }
                }
                else
                {
                    MessageBox.Show(string.Format("File at path '{0}' could not be found. Please check the file path and try again. ", xmlPath), "File not found");
                }
            }
            else
            {
                MessageBox.Show(string.Format("File at path is not valid. Please check the file path and try again. ", xmlPath), "Invalid File Path");
            }
        }

        private void ProcessBatch()
        {
            Batch batch = new Batch();
            string xmlPath = this.textBoxXmlPath.Text;
            int errors = 0;
            int operations = 0;
            bool results = false;

            if (xmlPath.Length > 0)
            {
                if (System.IO.File.Exists(xmlPath))
                {
                    string xml = FileHelper.Read(xmlPath);
                    batch = Batch.Deserialize(xml) as Batch;
                    progressBar1.Maximum = batch.Tasks.Count;
                    progressBar1.Minimum = 0;
                    progressBar1.Value = 0;

                    foreach (Task t in batch.Tasks)
                    {
                        operations++;
                        try
                        {
                            SPList list = SPOperations.GetList(t.SPWebUrl, t.ListName);
                            if (list == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or ListName.");
                            }
                            SPField field = SPOperations.GetField(t.SPWebUrl, t.ListName, t.FieldName);
                            if (field == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or ListName or FieldName.");
                            }

                            SPList lookupList = SPOperations.GetList(t.SPWebUrl, t.LookupListName);
                            if (lookupList == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or LookupListName.");
                            }

                            SPField lookupListField = SPOperations.GetField(t.SPWebUrl, t.LookupListName, t.LookupListFieldName);
                            if (lookupListField == null)
                            {
                                throw new ArgumentException("Invalid SPWebUrl or LookupListName or LookupListFieldName.");
                            }

                            results = SPOperations.RecreateLookupField(list, field, lookupList, lookupListField);

                            if (!results)
                            {
                                errors++;
                            }
                        }
                        catch (Exception ex)
                        {
                            ShowError(string.Format("An error has occurred whilst processing Field({0}) of List({1}).", t.FieldName, t.ListName), ex);
                            if (!results)
                            {
                                errors++;
                            }
                        }
                        progressBar1.Value++;
                    }
                    MessageBox.Show(string.Format("{0} operations completed with {1} errors.", operations, errors), "Operation Complete");
                }
                else
                {
                    MessageBox.Show(string.Format("File at path '{0}' could not be found. Please check the file path and try again. ", xmlPath), "File not found");
                }
            }
            else
            {
                MessageBox.Show(string.Format("File at path is not valid. Please check the file path and try again. ", xmlPath), "Invalid File Path");
            }
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            this.textBoxXmlPath.Text = openFileDialog1.FileName;
        }

        private void buttonBrowse_Click(object sender, EventArgs e)
        {
            openFileDialog1.Multiselect = false;
            openFileDialog1.ShowDialog();
        }

        private void About_Click(object sender, EventArgs e)
        {
            MessageBox.Show(string.Format("{0}\n{1}",SPLookupLinker.Properties.Resources.Version, SPLookupLinker.Properties.Resources.AboutInfo), SPLookupLinker.Properties.Resources.AboutCaption);
        }

    }
}